import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
import { ExtractJwt } from 'passport-jwt';
import { validateJwt } from 'src/app/auth/app.strategy';
import { LoggerService } from 'src/common/modules/logger/logger.service';
import { IHttpLog } from 'src/common/modules/logger/logger.types';

@Injectable()
export class RateLimitMiddleware implements NestMiddleware {
	private requestsPerSecond = new Map<string, number>();
	private readonly maxRequestsPerSecond = 1;

	constructor(private readonly loggerService: LoggerService) {}

	use(req: Request, res: Response, next: NextFunction) {
		let token="Bearer "+ExtractJwt.fromAuthHeaderAsBearerToken()(req)
		let userId
		if(token){
			let user=validateJwt(token)
			if(!user){
				next();
				return
			}
			userId=(user.roleId||user._id)+"_"+req.method+"_"+req.originalUrl
			// 检查当前用户请求数量是否超过限制
			if (req.method!="GET"&&this.getRequestsCount(userId) >= this.maxRequestsPerSecond) {
				// let logParams:IHttpLog={
				// 	trackId:"",
				// 	user: "",
				// 	url: req.originalUrl,
				// 	method: req.method,
				// 	timeMs: 0,
				// 	headers: req.headers,
				// 	params: req.params,
				// 	body: req.body,
				// 	responseFrom:"db",
				// 	responseCode:429,
				// 	responseData:null
				// }
				// this.loggerService.writeHttpLog(logParams)
				res.status(429).json({ message: 'Too Many Requests' });
				return;
			}

			// 增加计数器
			this.incrementRequestsCount(userId);

			// 重置计数器
			setTimeout(() => {
				this.decrementRequestsCount(userId);
			}, 100);

			// 允许请求继续处理
			next();
		}else{
			next();
		}

	}

	private getRequestsCount(userId: string): number {
		return this.requestsPerSecond.get(userId) || 0;
	}

	private incrementRequestsCount(userId: string): void {
		const count = this.getRequestsCount(userId);
		this.requestsPerSecond.set(userId, count + 1);
	}

	private decrementRequestsCount(userId: string): void {
		const count = this.getRequestsCount(userId);
		if (count > 0) {
			this.requestsPerSecond.set(userId, count - 1);
			if(this.requestsPerSecond.get(userId)<=0){
				this.requestsPerSecond.delete(userId)
			}
		}
	}
}
